#pragma once
#include <cstddef>
#include <new.h>
#include "TypeTrait.h"

namespace mini
{
	struct inputIteratorTag
	{

	};

	struct outputIteratorTag
	{

	};

	struct forwardIteratorTag : public inputIteratorTag
	{

	};

	struct bidirectionalIteratorTag : public forwardIteratorTag
	{

	};

	struct randomIteratorTag : public bidirectionalIteratorTag
	{

	};

	template<class I>
	struct iteratorTrait
	{
		typedef typename I::iterator_category iterator_category;
		typedef typename I::value_type value_type;
		typedef typename I::difference_type difference_type;
		typedef typename I::pointer pointer;
		typedef typename I::reference reference;
	};
	template<class I>
	struct iteratorTrait<I*>
	{
		typedef randomIteratorTag iterator_category;
		typedef ptrdiff_t difference_type;
		typedef I* value_type;
		typedef I* pointer;
		typedef I& reference;
	};

	template<class I>
	struct iteratorTrait<const I*>
	{
		typedef randomIteratorTag iterator_category;
		typedef ptrdiff_t difference_type;
		typedef const I* value_type;
		typedef const I* pointer;
		typedef const I& reference;
	};

	template<class Iterator>
	typename iteratorTrait<Iterator>::iterator_category
	iterator_category(const Iterator&)
	{
		typedef typename iteratorTrait<Iterator>::iterator_category iterator_category;
		return iterator_category();
	}


	template<class Iterator>
	typename iteratorTrait<Iterator>::difference_type
	difference_type(const Iterator&)
	{
		typedef typename iteratorTrait<Iterator>::difference_type difference_type;
		return difference_type();
	}
	
	template<class Iterator>
	typename iteratorTrait<Iterator>::value_type
	value_type(const Iterator&)
	{
		typedef typename iteratorTrait<Iterator>::value_type value_type;
		return value_type();
	}
}